﻿/**
* Makes a ComboBox more closely mimic an HTML SELECT.  Supports clicking and dragging
* through the list, with item selection occurring when the mouse button is released.
* When used will automatically set {@link #editable} to false and call {@link Ext.Element#unselectable}
* on inner elements.  Re-enabling editable after calling this will NOT work.
*
* @author Corey Gilmore
* http://extjs.com/forum/showthread.php?t=6392
*
* @history 2007-07-08 jvs
* Slight mods for Ext 2.0
*/
Ext.ux.SelectBox = function (config) {
    this.searchResetDelay = 1000;
    config = config || {};
    config = Ext.apply(config || {}, {
        editable: false,
        forceSelection: true,
        rowHeight: false,
        lastSearchTerm: false,
        triggerAction: 'all',
        mode: 'local'
    });
    Ext.ux.SelectBox.superclass.constructor.apply(this, arguments);
    this.lastSelectedIndex = this.selectedIndex || 0;
};

Ext.extend(Ext.ux.SelectBox, Ext.form.ComboBox, {
    lazyInit: false,
    initEvents: function () {
        Ext.ux.SelectBox.superclass.initEvents.apply(this, arguments);
        //你需要使用按键捕获大/小写和Shift+钥匙，但在IE中不起作用
        this.el.on('keydown', this.keySearch, this, true);
        this.cshTask = new Ext.util.DelayedTask(this.clearSearchHistory, this);
    }, keySearch: function (e, target, options) {
        var raw = e.getKey();
        var key = String.fromCharCode(raw);
        var startIndex = 0;
        if (!this.store.getCount()) {
            return;
        }
        switch (raw) {
            case Ext.EventObject.HOME:
                e.stopEvent();
                this.selectFirst();
                return;

            case Ext.EventObject.END:
                e.stopEvent();
                this.selectLast();
                return;

            case Ext.EventObject.PAGEDOWN:
                this.selectNextPage();
                e.stopEvent();
                return;

            case Ext.EventObject.PAGEUP:
                this.selectPrevPage();
                e.stopEvent();
                return;
        }
        //跳过以外的其他特殊键Shift键
        if ((e.hasModifier() && !e.shiftKey) || e.isNavKeyPress() || e.isSpecialKey()) {
            return;
        }
        if (this.lastSearchTerm == key) {
            startIndex = this.lastSelectedIndex;
        }
        this.search(this.displayField, key, startIndex);
        this.cshTask.delay(this.searchResetDelay);
    }, onRender: function (ct, position) {
        this.store.on('load', this.calcRowsPerPage, this);
        Ext.ux.SelectBox.superclass.onRender.apply(this, arguments);
        if (this.mode == 'local') {
            this.calcRowsPerPage();
        }
    }, onSelect: function (record, index, skipCollapse) {
        if (this.fireEvent('beforeselect', this, record, index) !== false) {
            this.setValue(record.data[this.valueField || this.displayField]);
            if (!skipCollapse) {
                this.collapse();
            }
            this.lastSelectedIndex = index + 1;
            this.fireEvent('select', this, record, index);
        }
    }, render: function (ct) {
        Ext.ux.SelectBox.superclass.render.apply(this, arguments);
        if (Ext.isSafari) {
            this.el.swallowEvent('mousedown', true);
        }
        this.el.unselectable();
        this.innerList.unselectable();
        this.trigger.unselectable();
        this.innerList.on('mouseup', function (e, target, options) {
            if (target.id && target.id == this.innerList.id) { return; }
            this.onViewClick();
        }, this);

        this.innerList.on('mouseover', function (e, target, options) {
            if (target.id && target.id == this.innerList.id) { return; }
            this.lastSelectedIndex = this.view.getSelectedIndexes()[0] + 1;
            this.cshTask.delay(this.searchResetDelay);
        }, this);

        this.trigger.un('click', this.onTriggerClick, this);
        this.trigger.on('mousedown', function (e, target, options) {
            e.preventDefault();
            this.onTriggerClick();
        }, this);

        this.on('collapse', function (e, target, options) {
            Ext.getDoc().un('mouseup', this.collapseIf, this);
        }, this, true);

        this.on('expand', function (e, target, options) {
            Ext.getDoc().on('mouseup', this.collapseIf, this);
        }, this, true);
    }, clearSearchHistory: function () {
        this.lastSelectedIndex = 0;
        this.lastSearchTerm = false;
    }, selectFirst: function () {
        this.focusAndSelect(this.store.data.first());
    }, selectLast: function () {
        this.focusAndSelect(this.store.data.last());
    }, selectPrevPage: function () {
        if (!this.rowHeight) {
            return;
        }
        var index = Math.max(this.selectedIndex - this.rowsPerPage, 0);
        this.focusAndSelect(this.store.getAt(index));
    }, selectNextPage: function () {
        if (!this.rowHeight) {
            return;
        }
        var index = Math.min(this.selectedIndex + this.rowsPerPage, this.store.getCount() - 1);
        this.focusAndSelect(this.store.getAt(index));
    }, search: function (field, value, startIndex) {
        field = field || this.displayField;
        this.lastSearchTerm = value;
        var index = this.store.find.apply(this.store, arguments);
        if (index !== -1) {
            this.focusAndSelect(index);
        }
    }, focusAndSelect: function (record) {
        var index = typeof record === 'number' ? record : this.store.indexOf(record);
        this.select(index, this.isExpanded());
        this.onSelect(this.store.getAt(record), index, this.isExpanded());
    }, calcRowsPerPage: function () {
        if (this.store.getCount()) {
            this.rowHeight = Ext.fly(this.view.getNode(0)).getHeight();
            this.rowsPerPage = this.maxHeight / this.rowHeight;
        } else {
            this.rowHeight = false;
        }
    }
});

Ext.Ajax.on('requestcomplete', function (ajax, xhr, o) {
    if (typeof urchinTracker == 'function' && o && o.url) {
        urchinTracker(o.url);
    }
});